home *** CD-ROM | disk | FTP | other *** search
/ Suzy B Software 2 / Suzy B Software CD-ROM 2 (1994).iso / new_file / mintprgs / mint112 / mint112d.lzh / appendix.e < prev    next >
Encoding:
Text File  |  1994-11-15  |  37.3 KB  |  776 lines

  1. Appendix E: MiNT File Systems
  2.  
  3. MiNT allows loadable file systems, which means that it should be quite
  4. easy to implement networked file systems, dynamically re-sizable ram
  5. disks, or other nifty things (for example, Stephen Henson's minix.xfs
  6. file system allows access to Minix partitions from TOS). Writing
  7. these is not difficult, but there are a lot of data structures that
  8. must be understood first. (These data structures are given in the
  9. Appendix D.)
  10.  
  11. A note on conventions: a declaration like:
  12.     short foo P_((char *bar, long baz));
  13. means that "foo" is a function that returns a 16 bit integer, and that
  14. expects a pointer to a character and a 32 bit integer as its two
  15. arguments. "ushort" is an unsigned 16 bit integer; "ulong" is an
  16. unsigned 32 bit integer.
  17.  
  18. File Cookies
  19.  
  20. Files and directories are represented in the kernel by "cookies".
  21. The contents of the cookie are mostly file system dependent, i.e. the
  22. kernel interprets only the "fs" and "dev" field of the cookie, and the
  23. contents of the other fields may be used by a file system as it sees fit.
  24.  
  25. A file cookie has the following structure:
  26.  
  27. typedef struct f_cookie {
  28.     FILESYS *fs;        /* file system that knows about this cookie */
  29.     ushort    dev;        /* device info (e.g. Rwabs device number) */
  30.     ushort    aux;        /* extra data that the file system may want */
  31.     long    index;        /* this+dev uniquely identifies a file */
  32. } fcookie;
  33.  
  34. (The "FILESYS" data type is defined below.)
  35. The interpretation of the "aux" field is entirely file system dependent. The
  36. "index" field is not presently used by the kernel, but file systems
  37. should (if possible) make this field uniquely identify a file or directory
  38. on a device.
  39.  
  40. File System Structure
  41.  
  42. This is the structure that tells the kernel about the file system,
  43. and gives the entry points for routines which the kernel can call in order
  44. to manipulate files and directories. Note that actual input/output
  45. operations are performed by a device driver; most file systems have just
  46. one associated device driver, but some may have more. See the section on
  47. device drivers for more information on these.
  48.  
  49. Unless otherwise specified, all of the functions should return 0 for
  50. success and an appropriate (long negative) error code for failure. Also,
  51. note that it is the kernel's responsibility to do all access checking;
  52. the file system may assume that the file's permissions have been checked
  53. and are compatible with the current process' uid and the operation
  54. selected.
  55.  
  56. Parameters are passed to file system driver functions on the stack.
  57. The file system drivers should preserve registers d2-d7 and a2-a7,
  58. and return any results in register d0. Note that this may differ from
  59. your compiler's default conventions (for example, Alcyon C preserves
  60. only registers d3-d7 and a3-a7); in this case, an assembly language
  61. wrapper will be necessary.
  62.  
  63. typedef struct filesys {
  64.     struct    filesys    *next;
  65.  
  66. This is a link to the next file system in the kernel's list. It will be
  67. filled in by the kernel; the file system should leave it as NULL.
  68.  
  69.     long    fsflags;
  70. These flags give some information about the file system. Currently, three
  71. flags are defined:
  72.  
  73. #define FS_KNOPARSE     0x01    /* kernel shouldn't do parsing */
  74. #define FS_CASESENSITIVE 0x02    /* file names are case sensitive */
  75. #define FS_NOXBIT     0x04    /* if a file can be read, it can be executed */
  76. #define FS_LONGPATH     0x08    /* the 'getname' function obeys the
  77.                    'size' argument restrictions */
  78.  
  79. Other bits may be defined in future releases of MiNT; for now all other
  80. bits in this flag should be 0. Most file systems will have only the
  81. FS_NOXBIT and FS_LONGPATH flags; networked file systems may have FS_KNOPARSE
  82. for reasons of efficiency, and file systems that must be compatible with Unix
  83. or similar specifications may be case sensitive and hence have FS_CASESENSITIVE
  84. set.
  85. See the description of the (*getname) function for details on the effects
  86. of the FS_LONGPATH flag.
  87.  
  88.     long    (*root) P_((short drv, fcookie *fc));
  89. This is the entry point for a routine to find a file cookie for the root
  90. directory of BIOS device "drv" (an integer in the range 0-31 inclusive).
  91. This function is called by the kernel when initializing a drive; the kernel
  92. will query each file system in turn for a file cookie representing the
  93. root directory of the drive. If the file system recognizes the data on
  94. the drive as being valid for a file system that it recognizes, it should
  95. fill in the cookie pointed to by "fc" and return 0. Otherwise, it should
  96. return a negative error code (EDRIVE is a good choice) to indicate that the
  97. drive must belong to another file system. Note that this function is called
  98. at boot up time and also at any time when media change is detected on a drive.
  99.  
  100.     long    (*lookup) P_((fcookie *dir, char *name, fcookie *fc));
  101. Translate a file name into a cookie. "dir" is the cookie for a directory,
  102. returned by a previous call to (*lookup) or (*root). "name" is either the
  103. name of a file in that directory (if fsflags & FS_KNOPARSE == 0) or a path
  104. name relative to that directory (if fsflags & FS_KNOPARSE == FS_KNOPARSE).
  105. If the file is not found, an appropriate error code (like EFILNF) should be
  106. returned. If the file is found, the cookie "*fc" should be filled in with
  107. appropriate data, and either 0 or EMOUNT returned. EMOUNT should be returned
  108. only if "name" is ".." and "dir" represents the root directory of a drive;
  109. 0 should be returned otherwise. Note that a lookup call with a null name
  110. or with "." should always succeed and return a cookie representing the
  111. directory itself. Also note that symbolic links should *never* be followed.
  112.  
  113.     long    (*creat) P_((fcookie *dir, char *name, ushort mode,
  114.                 short attrib, fcookie *fc)
  115. Create a new file named "name" in the directory whose cookie is "dir".
  116. "mode" gives the file's type and access permissions, as follows:
  117.     /* file types */
  118.     #define S_IFMT    0170000        /* mask to select file type */
  119.     #define S_IFCHR    0020000        /* BIOS special file */
  120.     #define S_IFDIR    0040000        /* directory file */
  121.     #define S_IFREG 0100000        /* regular file */
  122.     #define S_IFIFO 0120000        /* FIFO */
  123.     #define S_IMEM    0140000        /* memory region or process */
  124.     #define S_IFLNK    0160000        /* symbolic link */
  125.  
  126.     /* special bits: setuid, setgid, sticky bit */
  127.     #define S_ISUID    04000        /* change euid when executing this file */
  128.     #define S_ISGID 02000        /* change egid when executing this file */
  129.     #define S_ISVTX    01000        /* not implemented */
  130.  
  131.     /* file access modes for user, group, and other*/
  132.     #define S_IRUSR    0400        /* read access for user */
  133.     #define S_IWUSR 0200        /* write access for user */
  134.     #define S_IXUSR 0100        /* execute access for user */
  135.     #define S_IRGRP 0040        /* ditto for group... */
  136.     #define S_IWGRP    0020
  137.     #define S_IXGRP    0010
  138.     #define S_IROTH    0004        /* ditto for everyone else */
  139.     #define S_IWOTH    0002
  140.     #define S_IXOTH    0001
  141.  
  142. "attrib" gives the standard TOS attribute byte. This is slightly redundant
  143. with "mode" (i.e. the FA_RDONLY bit should agree with the settings of
  144. S_IWUSR, S_IWGRP, and S_IWOTH, and FA_DIR should be set if and only if
  145. the file's format is S_IFDIR) but is provided for convenience for standard
  146. DOS compatible file systems.
  147.  
  148. The kernel will make the "creat" call only after using "lookup" in an attempt
  149. to find the file. The file system should create the file (if possible) and
  150. set the cookie pointed to by "fc" to represent the newly created file.
  151. If an error of any sort occurs, an appropriate error number is returned,
  152. otherwise 0 is returned. Also note that the kernel will not try to
  153. create directories this way; it will use "mkdir" (q.v.) instead.
  154.  
  155.     DEVDRV *(*getdev) P_((fcookie *fc, long *devspecial))
  156. Get the device driver which should be used to do i/o on the file whose
  157. cookie is "fc". If an error occurs, a NULL pointer should be returned
  158. and an error code placed in the long pointed to by "devspecial"; otherwise,
  159. "devspecial" should be set to a device-driver specific value which will
  160. be placed by the kernel in the "devinfo" field of the FILEPTR structure
  161. passed to the device driver's open routine. (The interpretation of
  162. this value is a matter for the file system and the device driver, the
  163. kernel doesn't care.)
  164.  
  165. If the call to (*getdev) succeeds, a pointer to a device driver structure
  166. (see below) is returned; if it fails, a NULL pointer should be returned and
  167. an appropriate error number placed in *devspecial.
  168.  
  169.     long    (*getxattr) P_((fcookie *file, XATTR *xattr));
  170. Get a file's attributes. The XATTR structure pointed to by "xattr" should
  171. be filled in with the data for the file or directory represented by
  172. the cookie "*file", and 0 returned. If a fatal error occurs (e.g. media
  173. change) an error code is returned instead. The XATTR structure is defined
  174. as follows:
  175.  
  176. /* structure for getxattr */
  177.     typedef struct xattr {
  178.     ushort    mode;
  179. file types and permissions; same as the mode passed to (*creat) (see above)
  180.     long    index;
  181. file index; this should if possible be a unique number for the file, so that
  182. no two files on the same physical drive could have the same index. It is
  183. not mandatory that this match the "index" field of the fcookie structure
  184. for the file.
  185.     ushort    dev;
  186. physical device on which the file is located; normally set to file->dev
  187.     ushort    reserved1;
  188. set to 0
  189.     ushort    nlink;
  190. number of hard links to the file; normally 1
  191.     ushort    uid;
  192. a number representing the user that owns the file
  193.     ushort    gid;
  194. the group ownership of the file
  195.     long    size;
  196. length of the file, in bytes
  197.     short    mtime, mdate;
  198. last modification time and date of the file, in standard GEMDOS format
  199.     short    atime, adate;
  200. last access time and date for the file, in standard GEMDOS format; if the
  201. file system does not keep separate record of these, they should be the same
  202. as mtime and mdate
  203.     short    ctime, cdate;
  204. file creation time and date, in standard GEMDOS format; if the file system
  205. does not keep separate record of these, they should be the same as mtime
  206. and mdate
  207.     short    attr;
  208. TOS attribute byte for the file in the lower 8 bits; the upper 8 should
  209. be 0
  210.     short    reserved2;
  211. reserved, set to 0
  212.     long    reserved3[2];
  213. reserved, set both long words to 0
  214.     } XATTR;
  215.  
  216.     long    (*chattr) P_((fcookie *file, short attr));
  217. Change the TOS attributes of the file whose cookie is "*file" to "attr".
  218. Only the lower 8 bits of "attr" should be considered significant, for now.
  219. The kernel will not allow changes if the file's current attributes include
  220. the FA_DIR bit or the FA_LABEL bit. Not all filesystems will support all
  221. TOS attribute bits, but FA_RDONLY should probably be supported if possible;
  222. usually setting the FA_RDONLY bit should be equivalent to turning off all
  223. write permissions to the file.
  224.  
  225.     long    (*chown) P_((fcookie *file, short uid, short gid));
  226. Change a file's user and group ownership to "uid" and "gid" respectively.
  227. The kernel checks access permissions before making this call, so file
  228. systems do not have to. If the file system does not support a concept
  229. of ownership, or does not allow changes to ownership, it should return
  230. EINVFN.
  231.  
  232.     long    (*chmode) P_((fcookie *file, ushort mode));
  233. Change a file's access permissions. "mode" is similar to the field in
  234. the XATTR structure or the value passed to creat, except that _only_
  235. the permission bits are significant; (mode & S_IFMT) will always be 0.
  236. In the event that the file system supports only a subset of permissions
  237. (e.g. the TOS file system can only control write access to the file)
  238. then it may consider only the relevant bits of "mode".
  239.  
  240.     long    (*mkdir) P_((fcookie *dir, char *name, ushort mode));
  241. Make a new subdirectory called "name" of the directory whose cookie is
  242. "*dir". The new directory should have the file permissions given by
  243. "mode & ~S_IFMT". Note that the file system should do all appropriate
  244. initializations for the new directory, including making entries for
  245. "." and "..". Note also that the kernel verifies that "mode & S_IFMT"
  246. is S_IFDIR before making this call.
  247.  
  248.     long    (*rmdir) P_((fcookie *dir, char *name));
  249. Delete the subdirectory called "name" of the directory whose cookie is
  250. "*dir". It is also a good idea to allow removal of symbolic links via
  251. this call, since a symbolic link to a directory looks like a directory
  252. to a normal TOS program.
  253.  
  254.     long    (*remove) P_((fcookie *dir, char *name));
  255. Delete the file called "name" in the directory "*dir". This function should
  256. act like the Unix "unlink" call, i.e. if the file has more than 1 hard
  257. link to it, only this particular link to the file should be removed and
  258. the file contents should not be affected. Directories should not be removed
  259. by this function. Symbolic links definitely should be removed by this
  260. function; whether other types of special files are removed by this function
  261. is up to the file system.
  262.  
  263.     long    (*getname) P_((fcookie *relto, fcookie *dir, char *pathname,
  264.                    short size));
  265. This is analogous to the "getcwd()" operation in Unix. It should get the name
  266. of the directory whose cookie is "*dir", expressed as a path relative
  267. to the directory whose cookie is "*relto"; normally, this is the root
  268. directory, but the file system should not assume this. The resulting path
  269. is placed in the array pointed to by pathname, which is at least
  270. "size" bytes long. If *relto and *dir are the same directory, then an empty
  271. string should be placed in *pathname. If the complete path name (including
  272. trailing 0, if any) will not fit into the space provided, then ERANGE
  273. should be returned; in this case *pathname may or may not have any
  274. meaningful information stored into it (i.e., a partial pathname may be,
  275. but need not be, returned).
  276.  
  277. Note: The "size" argument is a new feature (added in MiNT 0.97). New file
  278. systems should always respect this argument, and indicate this by setting
  279. the FS_LONGPATH bit in the "fsflags" field of the FILESYS structure.
  280. If FS_LONGPATH is clear, the kernel will assume that the file system is
  281. an old file system which always assumes a 128 byte maximum path size.
  282.  
  283. Example: if "*relto" is the directory "\FOO", and "*dir" is the directory
  284. "\FOO\BAR\SUB", then after the call to (*getname) "pathname" should contain
  285. "\BAR\SUB" (assuming that "size" is at least 9).
  286.  
  287.     long    (*rename) P_((fcookie *olddir, char *oldname,
  288.                 fcookie *newdir, char *newname));
  289. Rename the file with name "oldname" contained in the directory whose cookie
  290. is "*olddir" to the name "newname" in the directory whose cookie is "*newdir".
  291. The file system need not actually support cross-directory renames, or
  292. indeed any sort of renames at all; if no renames at all are supported, EINVFN
  293. should be returned.
  294.  
  295.     long    (*opendir) P_((DIR *dirh, short tosflag));
  296. Open a directory for reading. "dirh" is a pointer to a structure as defined
  297. below; the file cookie for the directory being opened may be found there.
  298. "tosflag" is a copy of "dirh->flags" and is in a sense redundant. The
  299. file system should initialize the "fsstuff" and "index" fields of "*dirh"
  300. to whatever it needs for carrying out a successful search.
  301.  
  302. /* structure for opendir/readdir/closedir */
  303. typedef struct dirstruct {
  304.     fcookie fc;        /* cookie for this directory */
  305.     ushort    index;        /* index of the current entry */
  306.     ushort    flags;        /* flags (e.g. tos or not) */
  307. #define TOS_SEARCH    0x01
  308. /* if TOS_SEARCH is set, this call originated from a TOS Fsfirst() system
  309.  * call -- if possible, the returned names should be acceptable to a
  310.  * "naive" TOS program
  311.  */
  312.     char    fsstuff[60];    /* anything else the file system wants */
  313. } DIR;
  314.  
  315.     long    (*readdir) P_((DIR *dirh, char *name, short namelen, fcookie *fc));
  316. Read the next name from the directory whose DIR structure (see above)
  317. is "*dirh". The name should be copied into "name" (if dirh->flags & TOS_SEARCH
  318. is nonzero) or "name+4" if dirh->flags & TOS_SEARCH is 0; in the latter case,
  319. the first 4 bytes of "name" should be a unique index for the file. "namelen"
  320. is the total size of the buffer for "name"; if the next file name (plus index,
  321. if appopriate, and including the trailing 0) is too long for the buffer, as
  322. much of it as will fit should be copied in and ENAMETOOLONG returned. If no
  323. more file names remain unread in the directory, ENMFIL should be returned
  324. and "name" left unchanged. Otherwise, 0 should be returned.
  325. Note that volume labels should not be read by this function; only
  326. "readlabel" (q.v.) should see these.
  327.  
  328.     long    (*rewinddir) P_((DIR *dirh));
  329. Reset the file system specific fields of "*dirh" so that the next call to
  330. "readdir" on this directory will return the first file name in the directory.
  331.  
  332.     long    (*closedir) P_((DIR *dirh));
  333. Called by the kernel when the directory "*dirh" is not going to be searched
  334. any more; if the file system needs to clean up any structures or free memory
  335. allocated for the search it can do so here.
  336.  
  337.     long    (*pathconf) P_((fcookie *dir, short which));
  338. Get path configuration information for the directory whose cookie is
  339. "*dir". "which" indicates what kind of information should be returned,
  340. as follows:
  341.  
  342. /* The requests for pathconf() */
  343. #define DP_IOPEN    0    /* internal limit on # of open files */
  344. #define DP_MAXLINKS    1    /* max number of hard links to a file */
  345. #define DP_PATHMAX    2    /* max path name length */
  346. #define DP_NAMEMAX    3    /* max length of an individual file name */
  347. #define DP_ATOMIC    4    /* # of bytes that can be written atomically */
  348. #define DP_TRUNC    5    /* file name truncation behavior */
  349. /* possible return values for DP_TRUNC */
  350. #    define    DP_NOTRUNC    0    /* long names cause an error */
  351. #    define    DP_AUTOTRUNC    1    /* long names are truncated */
  352. #    define    DP_DOSTRUNC    2    /* DOS 8+3 rules are used */
  353. #define DP_CASE        6    /* file name case conversion */
  354. /* possible values returned for DP_CASE */
  355. #    define    DP_CASESENS    0    /* case sensitive */
  356. #    define    DP_CASECONV    1    /* case always converted */
  357. #    define    DP_CASEINSENS    2    /* case insensitive, preserved */
  358.  
  359. #define DP_MAXREQ    6    /* highest legal request */
  360. /* Dpathconf and Sysconf return this when a value is not limited
  361.    (or is limited only by available memory) */
  362. #define UNLIMITED    0x7fffffffL
  363.  
  364.     long    (*dfree) P_((fcookie *dir, long *buf));
  365. Determine bytes used and free on the disk that the directory whose cookie
  366. is "*dir" is contained on. "buf" points to the same kind of buffer that
  367. the "Dfree" system call uses; see the documentation for that call.
  368.  
  369.     long    (*writelabel) P_((fcookie *dir, char *name));
  370. Create a volume label with the indicated name on the drive which contains
  371. the directory whose cookie is "*dir". If a label already exists, the file
  372. system may either fail the call with EACCDN or re-write the label. If the
  373. file system doesn't support the notion of labels, it should return EINVFN.
  374.  
  375.     long    (*readlabel) P_((fcookie *dir, char *name, short namelen));
  376. Read the volume label for the disk whose root directory has the cookie
  377. "*dir" into the buffer "name", which is "namelen" bytes long. If the
  378. volume label (including trailing 0) won't fit, return ENAMETOOLONG. If
  379. *dir is not the cookie of a root directory, or if no volume label
  380. exists (perhaps because the file system doesn't support them), return
  381. EFILNF.
  382.  
  383.     long    (*symlink) P_((fcookie *dir, char *name, char *to));
  384. Create a symbolic link called "name" in the directory whose cookie is
  385. "*dir". The link should contain the 0-terminated string "to". If the file
  386. system doesn't support symbolic links, it should return EINVFN.
  387.  
  388.     long    (*readlink) P_((fcookie *file, char *buf, short buflen));
  389. Read the contents of the symbolic link whose cookie is "*file" into the
  390. buffer "buf", which is "buflen" bytes long. If the contents (including the
  391. trailing 0) won't fit, return ENAMETOOLONG; if the file system doesn't
  392. do symbolic links, return EINVFN.
  393.  
  394.     long    (*hardlink) P_((fcookie *fromdir, char *fromname,
  395.                 fcookie *todir, char *toname));
  396. Create a hard link called "toname" in the directory whose cookie is
  397. "*todir" for the file named "fromname" in the directory whose cookie is
  398. "*fromdir". If the file system doesn't do hard links, return EINVFN.
  399.  
  400.     long    (*fscntl) P_((fcookie *dir, char *name, short cmd, long arg));
  401. Perform an operation on the file whose name is "name", in the directory with
  402. cookie "*dir". "cmd" and "arg" specify the operation, and are file system
  403. specific. See the documentation for Dcntl() for more details. Most file
  404. systems will just return EINVFN for any values of "cmd" and "arg"; this call
  405. is here so that you can provide users with a way to manipulate various special
  406. features of your file system.
  407.  
  408.     long    (*dskchng) P_((short drv));
  409. Check for media change. "drv" is the BIOS device number on which the
  410. kernel thinks there has been a change. This function is called only
  411. when the kernel detects what the BIOS claims is a definite disk change
  412. (i.e. Mediach returning 2 or Mediach returning 1 and Rwabs returning -14).
  413. This may be the result of a program trying to force a media change; if the
  414. file system agrees that a change has occured, it should perform any
  415. appropriate actions (e.g. invalidating buffers) and return 1; the kernel
  416. will then invalidate any open files or directories on the device and
  417. re-check what file system the device belongs  If no change, in fact, occured,
  418. a 0 should be returned to tell the kernel not to worry.
  419.  
  420.     long    (*release) P_((fcookie *fc));
  421. Called by the kernel to indicate that the cookie "*fc" is no longer
  422. in use. "*fc" was previously filled in by either the (*root)(),
  423. (*lookup)(), (*creat)(), (*readdir)(), or (*dupcookie)() call. "release"
  424. is called exactly once for each cookie, and should always succeed and
  425. return 0 to the kernel.
  426.  
  427.     long    (*dupcookie) P_((fcookie *dest, fcookie *src));
  428. Copy the fcookie given in "src" into "dest," and perform whatever
  429. file system specific bookkeeping is necessary to keep track of
  430. how many times a cookie is in use (if the file system cares).
  431. If the file system doesn't care, it should just do the
  432. equivalent of *dest = *src.
  433.  
  434. } FILESYS;
  435.  
  436. typedef struct fileptr {
  437.     short    links;        /* number of copies of this descriptor */
  438.     ushort    flags;        /* file open mode and other file flags */
  439. #define O_RWMODE      0x03    /* isolates file read/write mode */
  440. #    define O_RDONLY    0x00
  441. #    define O_WRONLY    0x01
  442. #    define O_RDWR    0x02
  443. #    define O_EXEC    0x03    /* execute file; used by kernel only */
  444.  
  445. #define O_APPEND    0x08    /* all writes go to the end of the file */
  446.  
  447. #define O_SHMODE    0x70    /* isolates file sharing mode */
  448. #    define O_COMPAT    0x00    /* compatibility mode */
  449. #    define O_DENYRW    0x10    /* deny both read and write access */
  450. #    define O_DENYW    0x20    /* deny write access to others */
  451. #    define O_DENYR    0x30    /* deny read access to others */
  452. #    define O_DENYNONE 0x40    /* don't deny any access to others */
  453.  
  454. #define O_NOINHERIT    0x80    /* children can't access via this file descriptor */
  455. #define O_NDELAY    0x100    /* don't block for i/o on this file */
  456. #define O_CREAT        0x200    /* create file if it doesn't exist */
  457. #define O_TRUNC        0x400    /* truncate file to 0 bytes if it does exist */
  458. #define O_EXCL        0x800    /* fail open if file exists */
  459. #define O_TTY        0x2000    /* file is a terminal */
  460. #define O_HEAD        0x4000    /* file is a pseudo-terminal "master" */
  461. #define O_LOCK        0x8000    /* file has been locked */
  462.  
  463. The "flags" is constructed by or'ing together exactly one read/write mode,
  464. one sharing mode, and any number of the other bits. Device drivers can
  465. ignore the O_CREAT flag, since file creation is handled by the kernel.
  466. The O_TRUNC flag, however, should be respected; the file should be
  467. truncated to 0 length if this flag is set.
  468.  
  469.     long    pos;        /* position in file */
  470. The kernel doesn't actually use this field, except to initialize it to
  471. 0; it is recommended that device drivers that allow seeking should use it
  472. to store the current position in the file (relative to the start of
  473. the file). Other device drivers may use it for other purposes.
  474.     long    devinfo;    /* device driver specific info */
  475. This field is passed back to the kernel from the file system from the
  476. "getdev" call; its interpretation is file system specific, except that
  477. if this is a terminal device (i.e. the O_TTY bit is set in "flags") then
  478. this must be a pointer to a struct tty for this terminal.
  479.     fcookie    fc;        /* file system cookie for this file */
  480. This is the cookie for the file, as returned by the file system "lookup"
  481. function during opening of the file.
  482.     struct devdrv *dev; /* device driver that knows how to deal with this */
  483. This is the device driver returned by the "getdev" call.
  484.     struct fileptr *next; /* link to next fileptr for this file */
  485. This field may be used by device drivers to keep a linked list of file
  486. pointers that refer to the same physical file, for example, in order to
  487. implement file sharing or locking code.
  488. } FILEPTR;
  489.  
  490.  
  491. The Device Driver Structure
  492.  
  493. All of the functions in the device driver structure, like those in the
  494. file system structure, are called in supervisor mode and with the
  495. GCC calling conventions. They must preserve registers d2-d7 and a2-a7,
  496. and results are to be returned in register d0. The BIOS, XBIOS,
  497. GEMDOS, AES, and VDI must not be called directly from the device
  498. driver; but GEMDOS and BIOS functions may be called indirectly via
  499. the tables found in the kerinfo structure.
  500.  
  501. typedef struct devdrv {
  502.     long (*open)    P_((FILEPTR *f));
  503. This routine is called by the kernel during a file "open", after it has
  504. constructed a FILEPTR for the file being opened and determined the device
  505. driver. The device driver should check the contents of the FILEPTR and
  506. make any changes or initializations necessary. If for some reason the open
  507. call should be failed, an appropriate error code must be returned (in which
  508. case the kernel will free the FILEPTR structure automatically). For example,
  509. if the file sharing mode in f->flags is not compatible with the sharing
  510. mode of another open FILEPTR referring to the same physical file, EACCDN should
  511. be returned.
  512.  
  513.     long (*write)    P_((FILEPTR *f, char *buf, long bytes));
  514. Write "bytes" bytes from the buffer pointed to by "buf" to the file with
  515. FILEPTR "f". Return the number of bytes actually written. If the file
  516. pointer has the O_APPEND bit set, the kernel will automatically perform
  517. an "lseek" to the end of the file before calling the "write" function.
  518. If the device driver cannot ensure the atomicity of the "lseek" + "write"
  519. combination, it should take whatever steps are necessary here to ensure
  520. that files with O_APPEND really do have all writes go to the end of the
  521. file.
  522.  
  523.     long (*read)    P_((FILEPTR *f, char *buf, long bytes));
  524. Read "bytes" bytes from the file with FILEPTR "f" into the buffer pointed
  525. to by "buf". Return the number of bytes actually read.
  526.  
  527.     long (*lseek)    P_((FILEPTR *f, long where, short whence));
  528. Seek to a new position in the file. "where" is the new position; "whence"
  529. says what "where" is relative to, as follows:
  530. /* lseek() origins */
  531. #define    SEEK_SET    0        /* from beginning of file */
  532. #define    SEEK_CUR    1        /* from current location */
  533. #define    SEEK_END    2        /* from end of file */
  534.  
  535.     long (*ioctl)    P_((FILEPTR *f, short mode, void *buf));
  536. Perform a device specific function. "mode" is the function desired. All devices
  537. should support the FIONREAD and FIONWRITE functions, and the file locking
  538. Fcntl functions if appropriate (see the documentation for the GEMDOS
  539. Fcntl function).
  540.  
  541.     long (*datime)    P_((FILEPTR *f, short *timeptr, short rwflag));
  542. Get or set the date/time of the file. "timeptr" is a pointer to two words,
  543. the first of which is the time and the second of which is the date.
  544. If "rwflag" is 0, the time and date of the file should be placed into timeptr.
  545. If "rwflag" is nonzero, then the time and date of the file should be set to
  546. agree with the time and date pointed to by timeptr.
  547.  
  548.     long (*close)    P_((FILEPTR *f, short pid));
  549. Called every time an open file is closed. Note that the file is "really"
  550. being closed if f->links == 0, otherwise, the FILEPTR is still being used
  551. by some process. However, if the device driver supports file locking
  552. then all locks held on the file by process pid should be released on
  553. any close, even if f->links > 0. Some things to watch out for:
  554. (1) "pid" is not necessarily the current process; some system calls
  555.     (e.g. Fmidipipe, Pexec) can sometimes close files in a process
  556.     other than the current one.
  557. (2) Device drivers should set the O_LOCK bit on f->flag when the F_SETLK
  558.     or F_SETLKW ioctl is made; they can then test for this bit when the file
  559.     is being closed, and remove locks only if O_LOCK is set. Note that all locks
  560.     held by process pid and referring to the same physical file as "f" may
  561.     be removed if O_LOCK is set, not just the locks that were associated with
  562.     the particular FILEPTR "f". If the FILEPTR has never had any lock Fcntl()
  563.     calls made on it, locks on the associated physical file need not be (and
  564.     should not be) removed when it is closed.
  565.  
  566.     long (*select)    P_((FILEPTR *f, long proc, short mode));
  567. Called by Fselect() when "f" is one of the file handles a user has chosen to
  568. do a select on. If mode is O_RDONLY, the select is for reading; if
  569. it is O_WRONLY, it is for writing (if it is for both reading and writing,
  570. the function will be called twice). The select function should return
  571. 1 if the device is ready for reading or writing (i.e. if a read or write
  572. call to the device will not block); otherwise, it should take whatever
  573. steps are necessary to arrange to wake up the process whose PROC structure is
  574. pointed to by "proc" when the appropriate I/O on the device becomes possible.
  575. Normally, this will be done by calling the "wakeselect" function (as passed
  576. by the kernel in "struct kerinfo") with "proc" as its parameter.
  577.  
  578.     void (*unselect) P_((FILEPTR *f, long proc, short mode));
  579. Called when the kernel is returning from an Fselect that had previously
  580. selected this file or device; the device driver should no longer notify
  581. "proc" when I/O is possible for this file or device. "mode" is the same
  582. mode as was passed to the select() function (see above), i.e. either
  583. O_RDONLY or O_WRONLY; as with select(), unselect() will be called twice
  584. if both input and output were selected for.
  585.  
  586.     long reserved[3];
  587. Reserved longwords for future expansion. These must be set to 0.
  588. } DEVDRV;
  589.  
  590.  
  591.  
  592. How the File System Is Booted
  593.  
  594. A loadable file system is an ordinary TOS executable file with an
  595. extension of ".xfs". MiNT searches its current directory (normally the
  596. root directory of the boot disk) when it is starting for all such
  597. files, and loads them with Pexec mode 3. It then does a jump to
  598. subroutine call to the first instruction of the loaded program,
  599. passing on the stack a pointer to a structure of type "struct kerinfo"
  600. (see below) which describes the version of MiNT and provides entry points
  601. for various utility functions.
  602.  
  603. The file system should *not* set up a stack or shrink its basepage
  604. (so the ordinary C startup code is not necessary). MiNT has already provided
  605. a stack of about 8K or so, and has shrunk the basepage to the bare minimum.
  606. The file system initialization point (like all file system functions) is
  607. called in supervisor mode; it must never switch back to user mode. It
  608. may use registers d0, d1, a0, and a1 as scratch registers; all other
  609. registers must be preserved.
  610.  
  611. What the file system initialization code *should* do is to check that an
  612. appropriate version of MiNT is running and to otherwise check the system
  613. configuration to see if it is appropriate for the file system driver.
  614. If so, a pointer to a FILESYS structure should be returned; if not, a NULL
  615. pointer should be returned.
  616.  
  617. Note that it is not necessary to actually check during initialization for
  618. the presence of disks with the appropriate file system types; MiNT will
  619. call the file system "root" function for each drive in the system, and so
  620. such checks should be done in the "root" function.
  621.  
  622. If the file system driver wishes to add new drives to the system,
  623. it should update the drive configuration variable stored at 0x4c2 to
  624. reflect the presence of these new drives.
  625.  
  626. File system drivers should *not* make any calls to the BIOS or GEMDOS
  627. directly; all such calls should be made through the vectors provided by
  628. the kernel as part of the struct kerinfo. File system drivers should
  629. never call the AES, VDI, or XBIOS.
  630.  
  631. All functions made visible to file systems through the kerinfo
  632. structure should be called using the GCC/Lattice C calling conventions,
  633. i.e.:
  634. (1) parameters are passed on the stack, aligned on 16 bit boundaries
  635. (2) registers d0-d1 and a0-a1 are scratch registers and may be modified
  636.     by the called functions
  637. (3) if the function returns a value, it will be returned in register
  638.     d0
  639.  
  640. /*
  641.  * this is the structure passed to loaded file systems to tell them
  642.  * about the kernel
  643.  */
  644.  
  645. typedef long (*Func)();
  646.  
  647. struct kerinfo {
  648.     short    maj_version;    /* kernel version number */
  649.     short    min_version;    /* minor kernel version number */
  650.     ushort    default_mode;    /* default file access permissions */
  651.     short    reserved1;    /* room for expansion */
  652.  
  653. /* OS functions */
  654. /* NOTE: these tables are definitely READ ONLY!!!! */
  655.     Func    *bios_tab;    /* pointer to the BIOS entry points */
  656.     Func    *dos_tab;    /* pointer to the GEMDOS entry points */
  657.  
  658. /* media change vector: call this if a device driver detects a disk
  659.  * change during a read or write operation. The parameter is the BIOS device
  660.  * number of the disk that changed.
  661.  */
  662.     void    (*drvchng) P_((ushort));
  663.  
  664. /* Debugging stuff */
  665.     void    (*trace) P_((char *, ...));    /* informational messages */
  666.     void    (*debug) P_((char *, ...));    /* error messages */
  667.     void    (*alert) P_((char *, ...));    /* really serious errors */
  668.     void    (*fatal) P_((char *, ...));    /* fatal errors */
  669.  
  670. /* memory allocation functions */
  671. /* kmalloc and kfree should be used for most purposes, and act like malloc
  672.  * and free respectively. umalloc and ufree may be used to allocate/free memory
  673.  * that is attached to the current process, and which is freed automatically
  674.  * when the process exits; this is generally not of much use to a file system
  675.  * driver
  676.  */
  677.     void *    (*kmalloc) P_((long));
  678.     void    (*kfree) P_((void *));
  679.     void *    (*umalloc) P_((long));
  680.     void    (*ufree) P_((void *));
  681.  
  682. /* utility functions for string manipulation */
  683.  
  684. /* strnicmp, stricmp: like strncmp and strcmp, respectively, except
  685.  * that case is ignored
  686.  */
  687.     short    (*strnicmp) P_((char *, char *, short));
  688.     short    (*stricmp) P_((char *, char *));
  689.  
  690. /* strlwr: convert a string to lower case. Returns the address of the string */
  691.     char *    (*strlwr) P_((char *));
  692. /* strupr: convert a string to upper case. Returns the address of the string */
  693.     char *    (*strupr) P_((char *));
  694.  
  695. /* sprintf: like the C library sprintf call, but using this one means you
  696.  * can avoid linking another one. Note: floating point formats are not
  697.  * supported! Also: this sprintf will put at most SPRINTF_MAX characters
  698.  * into the output string.
  699.  */
  700.     short    (*sprintf) P_((char *, const char *, ...));
  701.  
  702. /* utility functions for manipulating time */
  703. /* convert "ms" milliseconds into a DOS time (in td[0]) and date (in td[1]) */
  704.     void    (*millis_time) P_((ulong ms, short *td));
  705.  
  706. /* convert a DOS style time and date into a Unix style time; returns the
  707.  * Unix time
  708.  */
  709.     long    (*unixtim) P_((ushort time, ushort date));
  710.  
  711. /* convert a Unix time into a DOS time (in the high word of the returned
  712.  * value) and date (in the low word)
  713.  */
  714.     long    (*dostim) P_((long));
  715.  
  716. /* utility functions for dealing with pauses */
  717. /* go to sleep temporarily for about "n" milliseconds (the exact time
  718.  * slept may vary
  719.  */
  720.     void    (*nap) P_((ushort n));
  721.  
  722. /* wait on system queue "que" until a condition occurs */
  723.     void    (*sleep) P_((short que, long cond));
  724. /* wake all processes on queue "que" that are waiting for condition "cond" */
  725.     void    (*wake) P_((short que, long cond));
  726.  
  727. /* wake a process that is doing a select(); "param" should be the process
  728.  * code passed to select()
  729.  */
  730.     void    (*wakeselect) P_((long param));
  731.  
  732. /* file system utility functions */
  733. /* "list" is a list of open files; "f" is a new file that is being opened.
  734.  * If the file sharing mode of "f" conflicts with any of the FILEPTRs
  735.  * in the list, then this returns 1, otherwise 0.
  736.  */
  737.     short    (*denyshare) P_((FILEPTR *list, FILEPTR *f));
  738.  
  739. /* denylock() checks a list of locks to see if the new lock conflicts
  740.  * with any one in the list. If so, the first conflicting lock
  741.  * is returned; otherwise, a NULL is returned.
  742.  * This function is only available if maj_version > 0 or min_version >= 94.
  743.  * Otherwise, it will be a null pointer.
  744.  */
  745.     LOCK *    (*denylock) P_((LOCK *list, LOCK *new));
  746.  
  747. /*
  748.  * addtimeout() schedules a callback to occur at some future time
  749.  * "delta" is the number of milliseconds before the timeout is to occur,
  750.  * and func is a pointer to the function which should be called at that
  751.  * time. Note that the kernel's timeout facility does not actually have
  752.  * a millisecond resolution, so the function will most likely be called
  753.  * some time after specified time has elapsed (i.e. don't rely on this
  754.  * for really accurate timing). Also note that the timeout may occur
  755.  * in the context of a different process than the one which scheduled
  756.  * the timeout, i.e. the given function should not make assumptions involving
  757.  * the process context, including memory space.
  758.  * addtimeout() returns a long "magic cookie" which may be passed to
  759.  * the canceltimeout() function to cancel the pending time out.
  760.  * This function is only available in MiNT versions 1.06 and later;
  761.  * otherwise the pointer will be NULL.
  762.  */
  763.     long    (*addtimeout) P_((delta, void (*func)(void)));
  764.  
  765. /*
  766.  * canceltimeout() cancels a pending timeout. The parameter is the "magic
  767.  * cookie" returned from addtimeout(). If the timeout has already occured,
  768.  * canceltimeout does nothing, otherwise it removes the timeout from the
  769.  * kernel's schedule.
  770.  */
  771.     void    (*canceltimeout) P_((long));
  772.  
  773. /* reserved for future use */
  774.     long    res2[7];
  775. };
  776.